from collections import OrderedDict
import json


class Connection(tuple):

    ### CLASS ATTRIBUTES ###

    _fields = ('output', 'outlet', 'input', 'inlet')

    ### INITIALIZER ###

    def __new__(klass, output, outlet, input, inlet):

        from j264.tools.boxes.Box import Box

        assert isinstance(output, Box)
        assert isinstance(input, Box)
        assert output is not input
        assert output.patcher is not None
        assert output.patcher is input.patcher
        assert 0 <= outlet < output.outlet_count
        assert 0 <= inlet < input.inlet_count

        return tuple.__new__(klass, (output, outlet, input, inlet))

    ### SPECIAL METHODS ###

    def __getnewargs__(self):
        return tuple(self)

    ### SPECIAL PROPERTIES ###

    @property
    def __dict__(self):
        return OrderedDict(zip(self._fields, self))

    ### READ-ONLY PUBLIC PROPERTIES ###

    @property
    def inlet(self):
        return self[3]

    @property
    def input(self):
        return self[2]

    @property
    def json_data(self):
        self.source._update_ids_of_entire_tree_if_necessary()
        attrs = {
            'source': self.source.max_obj_id,
            'destination': self.target.max_obj_id,
            'hidden': 0,
            'midpoints': [],
        }
        return {self.max_obj_type: attrs}

    @property
    def json_format(self):
        return json.dumps(self.json_data, indent=4, sort_keys=True)

    @property
    def max_obj_type(self):
        return 'patchline'

    @property
    def outlet(self):
        return self[1]

    @property
    def output(self):
        return self[0]

    @property
    def source(self):
        return self.output

    @property
    def target(self):
        return self.input

